package cn.xdmnb.cloud.blog.plugin.gray.rule;

import cn.xdmnb.cloud.blog.core.constant.GrayConstant;
import cn.xdmnb.cloud.blog.plugin.gray.util.GrayRequestContextHolder;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.google.common.base.Optional;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.Server;
import com.netflix.loadbalancer.ZoneAvoidanceRule;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 灰度发布规则
 *
 * @author yukai
 * @since 2023年01月05日 23:15
 */
public class GrayRule extends ZoneAvoidanceRule {

    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }

    @Override
    public Server choose(Object key) {
        try {
            Boolean grayTag = GrayRequestContextHolder.getGrayTag().get();
            List<Server> reachableServers = this.getLoadBalancer().getReachableServers();
            List<Server> grayServers = new ArrayList<>();
            List<Server> normalServers = new ArrayList<>();
            for (Server reachableServer : reachableServers) {
                NacosServer nacosServer = (NacosServer) reachableServer;
                if (Objects.equals(nacosServer.getMetadata().get(GrayConstant.GRAY_HEADER), GrayConstant.GRAY_VALUE)){
                    grayServers.add(nacosServer);
                }else{
                    normalServers.add(nacosServer);
                }
            }
            if (grayTag){
                return originChoose(grayServers, key);
            }else{
                return originChoose(normalServers, key);
            }
        } finally {
            GrayRequestContextHolder.remove();
        }
    }

    private Server originChoose(List<Server> noMetaServerList, Object key){
        Optional<Server> serverOptional = getPredicate().chooseRoundRobinAfterFiltering(noMetaServerList, key);
        return serverOptional.orNull();
    }
}
